#region References

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D; 

#endregion

namespace PacketScreensaver.Windows.Screensaver
{
    #region Interface IEntity

    /// <summary>
    /// Represents a 3D network packet.
    /// </summary>
    interface IEntity
    {
        /// <summary>
        /// End point.
        /// </summary>
        Vector3 Destination { get; }

        /// <summary>
        /// Current position.
        /// </summary>
        Vector3 CurrentPosition { get; }

        /// <summary>
        /// Starting point.
        /// </summary>
        Vector3 InitialPosition { get; }

        /// <summary>
        /// Determines if a packet entity has arrived at its destination.
        /// </summary>
        bool HasArrived { get; }

        /// <summary>
        /// Representation of the network packet.
        /// </summary>
        Mesh Sphere { get; }

        /// <summary>
        /// Computs the next position for the entity.
        /// </summary>
        void CalculateNextPosition();
    } 

    #endregion

    /// <summary>
    /// Represents a 3D network packet.
    /// </summary>
    public class Entity : IEntity
    {
        #region Private Member Variables
        
        private Vector3 _destination;
        private Vector3 _currentPosition;
        private Vector3 _initialPosition;
        private Mesh _sphere;
        private float _dX;
        private float _dY;
        private float _dZ;  // speed
        private bool _hasArrived;
        private bool _isOutgoing; 

        #endregion

        #region Public Properties

        /// <summary>
        /// End point.
        /// </summary>
        public Vector3 Destination
        {
            get { return _destination; }
        }

        /// <summary>
        /// Current entity position
        /// </summary>
        public Vector3 CurrentPosition
        {
            get { return _currentPosition; }
        }

        /// <summary>
        /// Starting point.
        /// </summary>
        public Vector3 InitialPosition
        {
            get { return _initialPosition; }
        }

        /// <summary>
        /// Determines if a packet entity has arrived at its destination.
        /// </summary>
        public bool HasArrived
        {
            get { return _hasArrived; }
        }

        /// <summary>
        /// Representation of the network packet.
        /// </summary>
        public Mesh Sphere
        {
            get { return _sphere; }
        } 

        #endregion

        #region Construction / Destruction

        /// <summary>
        /// Constructs the Entity object.
        /// </summary>
        /// <param name="device"></param>
        /// <param name="initialPosition"></param>
        /// <param name="destination"></param>
        /// <param name="dz"></param>
        public Entity(Device device, Vector3 initialPosition, Vector3 destination, float dz)
        {
            _initialPosition = initialPosition;
            _destination = destination;
            _currentPosition = new Vector3(_initialPosition.X, _initialPosition.Y, _initialPosition.Z);
            _hasArrived = false;
            _dZ = dz;

            float length = destination.Z - initialPosition.Z;

            // determine the packet's direction
            if (length > 0)
                _isOutgoing = true;
            else
                _isOutgoing = false;

            float steps = length / _dZ;
            _dX = (destination.X - initialPosition.X) / steps;
            _dY = (destination.Y - initialPosition.Y) / steps;

            _sphere = Mesh.Sphere(device, .5f, 20, 20);
        }

        /// <summary>
        /// Finalizes the Entity object.
        /// </summary>
        ~Entity()
        {
            _sphere.Dispose();
            _sphere = null;
        } 

        #endregion

        #region Public Methods
        
        /// <summary>
        /// Calculates the next position of the packet entity.
        /// </summary>
        public void CalculateNextPosition()
        {
            _currentPosition.X += _dX;
            _currentPosition.Y += _dY;
            _currentPosition.Z += _dZ;

            if (_isOutgoing && _currentPosition.Z > _destination.Z)
                _hasArrived = true;
            else if (!_isOutgoing && _currentPosition.Z < _destination.Z)
                _hasArrived = true;
        } 

        #endregion
    }
}
